﻿using System;
using System.IO;
using System.Text;
using DGen;
using Tab2Sql.Classes;
using Tab2Sql.Classes.Core;
using NLog;

namespace Tab2Sql
{
    /// <summary>
    /// This class is for dealing with folders
    /// </summary>
    internal class multiFiles
    {
        private static Logger logger = LogManager.GetCurrentClassLogger ();
        /// <summary>
        /// Default constructor. Supplied path should be a valid directory with a set of schematically identical files.

        /// </summary>
        /// <param name="dirPath">
        /// A <see cref="System.String"/>
        /// </param>
        /// <param name="myOptions">
        /// A <see cref="Options"/>. This will be same object as supplied to the main tab2sql process carried out via the GUI.
        /// </param>
        public multiFiles(string dirPath, ref Options myOptions)
        {
            tablePrefix = "tab2sql_";

            DirectoryInfo dInfo = new DirectoryInfo(dirPath);
            if (dInfo.Exists == false)
            {
                return;
            }
            outputPath="";
            maximumBytes = myOptions.BatchSize;
            outputBytes = 0;
            DirectoryPath = dirPath;
            outputMessages = new StringBuilder();
            outputMessages.AppendLine("STARTED:" + DateTime.Now.ToLongTimeString());
            outputPath = Path.Combine(DirectoryPath, OutputFile);
            if (File.Exists(outputPath))
            {
                renameFile(outputPath, true);
            }
        }

        private void renameFile (string outputPath, bool useRandomName)
        {
            if (useRandomName == false)
            {
                return;
            }
            try
            {
                FileInfo f = new FileInfo (outputPath);
                string fNameBefore = Path.GetFileNameWithoutExtension (outputPath);
                string dName = Path.GetDirectoryName (outputPath);
                string eName = Path.GetExtension (outputPath);
                string fNameAfter = Path.Combine (dName, Path.GetRandomFileName () + eName);
                try
                {
                    f.MoveTo (fNameAfter);
                }
                catch (Exception ex)
                {
                    logger.Error ("Error renaming file. Message : {0} ", ex.Message);

                    outputMessages.AppendLine (ex.Message);
                }
            }
            catch (Exception ex2)
            {
                logger.Error ("Error renaming file. Message : {0} ", ex2.Message);
                outputMessages.AppendLine (ex2.Message);
            }

        }
        /// <summary>
        ///
        /// </summary>
        public string DirectoryPath = "";
        /// <summary>
        /// What file type are we processing? This has to be specified by a single file extension. Default is txt.
        /// </summary>
        public string FileExtension = "TXT";
        /// <summary>
        /// Because the output can be very large from this class the result is dumped to a file which by default is tab2sql_Generated.sql.
        /// This should be created in the current directory.
        /// </summary>
        public string OutputFile = "tab2sql_Generated.sql";
        private string outputPath;
        private long outputBytes;
        private string globalDelimiter = "\t";
        private string tablePrefix;
        /// <summary>
        /// Output target.
        /// </summary>
        public string OutputPath
        {
            get { return outputPath; }
            set { outputPath = value; }
        }
        
        private long maximumBytes;

        private StringBuilder outputMessages;


        /// <summary>
        /// This is the main repository for the end result.
        /// </summary>
        public string OutputMessages
        {
            get { return outputMessages.ToString(); }
        }
        /// <summary>
        /// Process files.
        /// </summary>
        public void Go ()
        {
            if (DirectoryPath.Length < 2)
            {
                DirectoryPath = Environment.CurrentDirectory;
            }
            var files = new string[300];
            files = Directory.GetFiles (DirectoryPath);
            int filesProcessedSoFar = 0;
            foreach (string filo in files)
            {
                if (filo.ToLower ().Contains ("csv") || filo.ToLower ().Contains ("txt"))
                {
                    outputMessages.AppendLine (filo);
                    if (File.Exists (filo) == true)
                    {
                        FileInfo fin = new FileInfo (filo);
                        if (fin.Length > maximumBytes)
                        {
                            logger.Info ("File supplied in main Go process is too large. Skipping. Supplied value was {0}", fin.Length);
                            outputMessages.AppendLine ("ERROR:File too big.");
                        }
                        else
                        {
                            String mainString = DGen.DFile.GetFileAsString (filo);
                            Options MyOptions = new Options ();
                            MyOptions.TableName = tablePrefix + Path.GetFileNameWithoutExtension (filo);
                            MyOptions.ColumnNameModel = HandlingOfColumnNames.Standard;
                            MyOptions.Delimiter = globalDelimiter;
                            MyOptions.StatementType = SqlStatementType.Standard;
                            MyOptions.IncludeQueryFooter = true;
                           
                            try
                            {

                                var tx100 = new xTab2Sql (mainString, MyOptions);
                                tx100.Process ();
                                var dt100 = new xDataTable2Sql (tx100);


                                // If this is the first file then we need the create table statement as well as the inserts.
                                if (filesProcessedSoFar == 0)
                                {
                                    DGen.DFile.WriteToFile (outputPath, dt100.CreateTable() + dt100.InsertInto().ToString(), true);
                                }
                                else
                                {
                                    DGen.DFile.WriteToFile (outputPath, dt100.InsertInto().ToString(), true);
                                }

                                filesProcessedSoFar++;
                            }
                            catch (Exception ex)
                            {

                                logger.Error ("Problem processing multi file. Files processed:{0}. File name {1}. Exception message:{2}", filesProcessedSoFar, filo, ex.Message);


                                outputMessages.AppendLine ("ERROR:" + ex.Message);
                            }

                            //
                        }
                    }
                    else
                    {
                        logger.Error("File not found. {0}.",filo);
                        outputMessages.AppendLine("ERROR:File not found.");
                    }
                }
            }
            outputMessages.AppendLine(outputPath);

        }
        /// <summary>
        /// Returns the total file size of the resulting output file in human readable format.
        /// </summary>
        /// <returns>
        /// A <see cref="System.String"/>
        /// </returns>
        public string OutputBytes()
        {
            if (outputPath.Length > 0)
            {
                FileInfo finito = new FileInfo(outputPath);
                outputBytes = finito.Length;
                finito = null;
                return DGen.DText.FormatBytes(outputBytes);
            }
            else
            {
                return "0";
            }
        }
    }
}